home *** CD-ROM | disk | FTP | other *** search
/ Scene 96 / Scene 96 International Edition (Zyklop Software) (Disc 2) (1997).iso / misc / coding / cp2dekit / samples / devssb.cpp < prev    next >
C/C++ Source or Header  |  1996-12-29  |  12KB  |  654 lines

  1. //***************************************************************************
  2. //
  3. // this file is (c) '94-'96 Niklas Beisert
  4. //
  5. // this file is part of the cubic player development kit.
  6. // you may only use/modify/spread this file under the terms stated
  7. // in the cubic player development kit accompanying documentation.
  8. //
  9. //***************************************************************************
  10.  
  11. //[sound]
  12. //  samplerdevices=devsSB
  13. //[devsSB]
  14. //  link=devssb
  15. //  driver=_smpSoundBlaster
  16. //  addprocs=_smpSBAdd
  17. //  sbrevstereo=off ;// some sb pros reverse stereo...
  18. //  handle=1
  19.  
  20.  
  21.  
  22.  
  23. // sampler sound device example
  24.  
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <dos.h>
  28. #include <ctype.h>
  29. #include <conio.h>
  30. #include "irq.h"
  31. #include "dma.h"
  32. #include "ss.h"
  33. #include "sampler.h"
  34.  
  35. #define SS_SB_REVSTEREO 1
  36.  
  37. extern "C" extern sounddevice smpSoundBlaster;
  38.  
  39. static signed short sbPort;
  40. static signed char sbIRQ;
  41. static signed char sbDMA;
  42. static signed char sbDMA16;
  43. static signed char sbUseVer;
  44. static char rightirq;
  45. static unsigned char sbSource;
  46. static unsigned char sbInSavL,sbInSavR;
  47.  
  48. static unsigned char getcfg()
  49. {
  50.   sbPort=-1;
  51.   sbIRQ=-1;
  52.   sbDMA=-1;
  53.   sbDMA16=-1;
  54.   sbUseVer=-1;
  55.   char *s=getenv("BLASTER");
  56.   if (!s)
  57.     return 0;
  58.   while (1)
  59.   {
  60.     while (isspace(*s))
  61.       s++;
  62.     if (!*s)
  63.       break;
  64.     switch (*s++)
  65.     {
  66.     case 'a': case 'A':
  67.       sbPort=strtoul(s, 0, 16);
  68.       break;
  69.     case 'i': case 'I':
  70.       sbIRQ=strtoul(s, 0, 10);
  71.       break;
  72.     case 'd': case 'D':
  73.       sbDMA=strtoul(s, 0, 10);
  74.       break;
  75.     case 'h': case 'H':
  76.       sbDMA16=strtoul(s, 0, 10);
  77.       break;
  78.     case 't': case 'T':
  79.       sbUseVer=strtoul(s, 0, 10);
  80.       switch (sbUseVer)
  81.       {
  82.       case 6: sbUseVer=4; break;
  83.       case 2: case 4: sbUseVer=3; break;
  84.       case 3: sbUseVer=2; break;
  85.       case 1: sbUseVer=1; break;
  86.       default: sbUseVer=-1;
  87.       }
  88.       break;
  89.     }
  90.     while (!isspace(*s)&&*s)
  91.       s++;
  92.   }
  93.   return 1;
  94. }
  95.  
  96. static unsigned char inpSB(unsigned char p)
  97. {
  98.   return inp(sbPort+p);
  99. }
  100.  
  101. static void outpSB(unsigned char p, unsigned char v)
  102. {
  103.   outp(sbPort+p,v);
  104. }
  105.  
  106. static void outSB(unsigned char v)
  107. {
  108.   while (inpSB(0xC)&0x80);
  109.   outpSB(0xC,v);
  110. }
  111.  
  112. static unsigned char inSB()
  113. {
  114.   while (!(inpSB(0xE)&0x80));
  115.   return inpSB(0xA);
  116. }
  117.  
  118. static void initSB()
  119. {
  120.   outpSB(0x6,1);
  121.   inpSB(0x6);
  122.   inpSB(0x6);
  123.   inpSB(0x6);
  124.   inpSB(0x6);
  125.   inpSB(0x6);
  126.   inpSB(0x6);
  127.   inpSB(0x6);
  128.   inpSB(0x6);
  129.   outpSB(0x6,0);
  130. }
  131.  
  132. static void initSBp()
  133. {
  134.   outpSB(0x6,1);
  135.   delay(100);
  136.   outpSB(0x6,0);
  137.   delay(100);
  138. }
  139.  
  140. static setrateSB(unsigned char r)
  141. {
  142.   outSB(0x40);
  143.   outSB(r);
  144. }
  145.  
  146. static void resetSB()
  147. {
  148.   inpSB(0xE);
  149. }
  150.  
  151. static void resetSB16()
  152. {
  153.   inpSB(0xF);
  154. }
  155.  
  156. static void spkronSB()
  157. {
  158.   outSB(0xD1);
  159. }
  160.  
  161. static void spkroffSB()
  162. {
  163.   outSB(0xD3);
  164. }
  165.  
  166. static void writeMixer(unsigned char p, unsigned char v)
  167. {
  168.   outpSB(0x4, p);
  169.   outpSB(0x5, v);
  170. }
  171.  
  172. static unsigned char readMixer(unsigned char p)
  173. {
  174.   outpSB(0x4, p);
  175.   return inpSB(0x5);
  176. }
  177.  
  178. static void test()
  179. {
  180.   rightirq=1;
  181. }
  182.  
  183. static char testPort(unsigned short port, int delay)
  184. {
  185.   sbPort=port;
  186.   if (delay)
  187.     initSBp();
  188.   else
  189.     initSB();
  190.   int i;
  191.   for (i=0; i<1000; i++)
  192.     if (inpSB(0xE)&0x80)
  193.       return inpSB(0xA)==0xAA;
  194.   return 0;
  195. }
  196.  
  197. static char testirq(unsigned char irq)
  198. {
  199.   irqInit(irq, test, 0);
  200.  
  201.   initSB();
  202.   setrateSB(0xD3);
  203.  
  204.   rightirq=0;
  205.  
  206.   outSB(0x80);
  207.   outSB(0x03);
  208.   outSB(0x00);
  209.   for (unsigned short i=0; i!=0xFFFF; i++)
  210.     if (rightirq)
  211.       break;
  212.  
  213.   irqClose();
  214.  
  215.   initSB();
  216.   resetSB();
  217.  
  218.   return rightirq;
  219. }
  220.  
  221. static char testdma(unsigned char irq, unsigned char dma)
  222. {
  223.   outp(0x0A,4);
  224.   outp(0x0A,5);
  225.   outp(0x0A,7);
  226.  
  227.   irqInit(irq, test, 0);
  228.   dmaStart(dma, 0, 10, 0x48);
  229.  
  230.   initSB();
  231.   setrateSB(0xD3);
  232.  
  233.   rightirq=0;
  234.  
  235.   outSB(0x14);
  236.   outSB(0x03);
  237.   outSB(0x00);
  238.   for (unsigned short i=0; i!=0xFFFF; i++)
  239.     if (rightirq)
  240.       break;
  241.   irqClose();
  242.   dmaStop();
  243.  
  244.   initSB();
  245.   resetSB();
  246.  
  247.   return rightirq;
  248. }
  249.  
  250. static char testdma16(unsigned char irq, unsigned char dma)
  251. {
  252.   outp(0x0A,4);
  253.   outp(0x0A,5);
  254.   outp(0x0A,7);
  255.   outp(0xD4,5);
  256.   outp(0xD4,6);
  257.   outp(0xD4,7);
  258.  
  259.   irqInit(irq, test, 0);
  260.   dmaStart(dma, 0, 2, 0x48);
  261.  
  262.   initSB();
  263.   setrateSB(0xEA);
  264.  
  265.   rightirq=0;
  266.  
  267.   outSB(0xB6);
  268.   outSB(0x10);
  269.   outSB(0x00);
  270.   outSB(0x00);
  271.   for (unsigned i=0; i!=0xFFFF; i++)
  272.     if (rightirq)
  273.       break;
  274.   irqClose();
  275.   dmaStop();
  276.  
  277.   initSB();
  278.   resetSB16();
  279.  
  280.   return rightirq;
  281. }
  282.  
  283. static unsigned short getVersion()
  284. {
  285.   outSB(0xE1);
  286.   while(1)
  287.   {
  288.     unsigned char verhi=inSB();
  289.     if (verhi==0xAA)
  290.       continue;
  291.     return ((unsigned short)verhi<<8)+inSB();
  292.   }
  293. }
  294.  
  295.  
  296.  
  297.  
  298. static void sb1Sampler()
  299. {
  300.   resetSB();
  301.   outSB(0x24);
  302.   outSB(0xFF);
  303.   outSB(0xFF);
  304.   inSB();
  305. }
  306.  
  307. static void sb2proSamplerHS()
  308. {
  309.   resetSB();
  310. }
  311.  
  312. static void sb16Player8()
  313. {
  314.   resetSB();
  315.   outSB(0x45);
  316. }
  317.  
  318. static void sb16Player16()
  319. {
  320.   outSB(0x47);
  321.   resetSB16();
  322. }
  323.  
  324. static unsigned char sbTimerConst;
  325. static unsigned char sbStereo;
  326. static unsigned char sb16Bit;
  327. static unsigned char sbSignedOut;
  328. static unsigned char revstereo;
  329.  
  330. static void sbSetSource(int src)
  331. {
  332.   sbSource=src;
  333. }
  334.  
  335. static void sbSetOptions(int rate, int opt)
  336. {
  337.   switch (sbUseVer)
  338.   {
  339.   case 1: case 2:
  340.     opt&=~(SMP_STEREO|SMP_16BIT|SMP_SIGNEDOUT);
  341.     break;
  342.   case 3:
  343.     opt&=~(SMP_16BIT|SMP_SIGNEDOUT);
  344.     break;
  345.   }
  346.   if (revstereo)
  347.     opt^=SMP_REVERSESTEREO;
  348.   sbStereo=!!(opt&SMP_STEREO);
  349.   sb16Bit=!!(opt&SMP_16BIT);
  350.   sbSignedOut=!!(opt&SMP_SIGNEDOUT);
  351.  
  352.   unsigned long rt=rate;
  353.   if ((sbUseVer==3)&&sbStereo)
  354.     rt<<=1;
  355.  
  356.   if (rt<4000)
  357.     rt=4000;
  358.   if (sbUseVer==4)
  359.     if (rt<5000)
  360.       rt=5000;
  361.   if ((sbUseVer==2)||(sbUseVer==3))
  362.     if (rt<8000)
  363.       rt=8000;
  364.  
  365.   if (rt>45454)
  366.     rt=45454;
  367.   if (sbUseVer==3)
  368.     if (rt>43478)
  369.       rt=43478;
  370.   if (sbUseVer==2)
  371.     if (rt>15151)
  372.       rt=15151;
  373.   if (sbUseVer==1)
  374.     if (rt>11111)
  375.       rt=11111;
  376.  
  377.   sbTimerConst=256-1000000/rt;
  378.   rate=1000000/(256-sbTimerConst);
  379.  
  380.   if ((sbUseVer==3)&&sbStereo)
  381.     rate>>=1;
  382.  
  383.   smpRate=rate;
  384.   smpOpt=opt;
  385. }
  386.  
  387. static int sbSample(void *buf, int &len)
  388. {
  389.   initSBp();
  390.   resetSB();
  391.   resetSB16();
  392.   setrateSB(sbTimerConst);
  393.   setrateSB(sbTimerConst);
  394.   spkroffSB();
  395.  
  396.   void (*playproc)();
  397.   switch (sbUseVer)
  398.   {
  399.   case 1:
  400.     playproc=sb1Sampler;
  401.     break;
  402.   case 2: case 3:
  403.     playproc=sb2proSamplerHS;
  404.     break;
  405.   case 4:
  406.     playproc=sb16Bit?sb16Player16:sb16Player8;
  407.     break;
  408.   }
  409.  
  410.   irqInit(sbIRQ, playproc, 0);
  411.   dmaStart(sb16Bit?sbDMA16:sbDMA, buf, len, 0x54);
  412.  
  413.   switch (sbUseVer)
  414.   {
  415.   case 1:
  416.     outSB(0x24);
  417.     outSB(0xFF);
  418.     outSB(0xFF);
  419.     inSB();
  420.     break;
  421.   case 2: case 3:
  422.     if (sbUseVer==3)
  423.       outSB(sbStereo?0xA8:0xA0);
  424.     outSB(0x48);
  425.     outSB(0xFF);
  426.     outSB(0xFF);
  427.     outSB(0x98);
  428.     inSB();
  429.     if (sbUseVer==3)
  430.     {
  431.       sbInSavL=readMixer(0x0C);
  432.       writeMixer(0x0C, (sbSource==SMP_MIC)?0x21:(sbSource==SMP_LINEIN)?0x27:0x23);
  433.     }
  434.     break;
  435.   case 4:
  436.     outSB(sb16Bit?0xBE:0xCE);
  437.     outSB((sbStereo?0x20:0x00)|(sbSignedOut?0x10:0x00));
  438.     outSB(0xFC);
  439.     outSB(0xFF);
  440.     sbInSavL=readMixer(0x3D);
  441.     sbInSavR=readMixer(0x3E);
  442.     writeMixer(0x3D, (sbSource==SMP_MIC)?0x01:(sbSource==SMP_LINEIN)?0x10:0x04);
  443.     writeMixer(0x3E, (sbSource==SMP_MIC)?0x01:(sbSource==SMP_LINEIN)?0x08:0x02);
  444.     break;
  445.   }
  446.  
  447.   smpGetBufPos=dmaGetBufPos;
  448.  
  449.   return 1;
  450. }
  451.  
  452.  
  453.  
  454. static void sbStop()
  455. {
  456.   switch (sbUseVer)
  457.   {
  458.   case 3:
  459.     writeMixer(0x0C, sbInSavL);
  460.     break;
  461.   case 4:
  462.     writeMixer(0x3D, sbInSavL);
  463.     writeMixer(0x3E, sbInSavR);
  464.     break;
  465.   }
  466.   irqClose();
  467.   dmaStop();
  468.   initSBp();
  469.   resetSB();
  470.   resetSB16();
  471. }
  472.  
  473.  
  474.  
  475. static int sbInit(const deviceinfo &card)
  476. {
  477.   if (!testPort(card.port, 1))
  478.     return 0;
  479.   resetSB();
  480.   resetSB16();
  481.  
  482.   revstereo=!!(card.opt&SS_SB_REVSTEREO);
  483.  
  484.   sbPort=card.port;
  485.   sbIRQ=card.irq;
  486.   sbDMA=card.dma;
  487.   sbDMA16=card.dma2;
  488.   unsigned char ver=getVersion()>>8;
  489.   if (card.subtype==-1)
  490.     sbUseVer=ver;
  491.   else
  492.     sbUseVer=card.subtype;
  493.   if (sbUseVer>ver)
  494.     return 0;
  495.   if ((sbUseVer==3)&&(ver==4))
  496.     return 0;
  497.  
  498. /*
  499.   if (!testirq(sbIRQ))
  500.     return 0;
  501.   if (!testdma(sbIRQ, sbDMA))
  502.     return 0;
  503.   if (sbUseVer==4)
  504.     if (!testdma16(sbIRQ, sbDMA16))
  505.       return 0;
  506. */
  507.  
  508.   smpSetOptions=sbSetOptions;
  509.   smpSetSource=sbSetSource;
  510.   smpSample=sbSample;
  511.   smpStop=sbStop;
  512.  
  513.   smpSetOptions(65535, SMP_STEREO|SMP_16BIT);
  514.   smpSetSource(SMP_LINEIN);
  515.  
  516.   return 1;
  517. }
  518.  
  519. static void sbClose()
  520. {
  521.   smpSample=0;
  522. }
  523.  
  524. static int sbDetect(deviceinfo &card)
  525. {
  526.   getcfg();
  527.   if (card.port!=-1)
  528.     sbPort=card.port;
  529.   if (card.irq!=-1)
  530.     sbIRQ=card.irq;
  531.   if (card.dma!=-1)
  532.     sbDMA=card.dma;
  533.   if (card.subtype!=-1)
  534.     sbUseVer=card.subtype;
  535.  
  536.   int i;
  537.   if (sbPort==-1)
  538.   {
  539.     unsigned short ports[]={0x220, 0x240, 0x260, 0x280, 0x210, 0x230, 0x250};
  540.     for (i=0; i<(sizeof(ports)>>1); i++)
  541.       if (testPort(ports[i],0))
  542.         break;
  543.     if (i==(sizeof(ports)>>1))
  544.       return 0;
  545.     sbPort=ports[i];
  546.   }
  547.   else
  548.     if (!testPort(sbPort, 0))
  549.       return 0;
  550.  
  551.   unsigned char ver=getVersion()>>8;
  552.   if (sbUseVer==-1)
  553.     sbUseVer=ver;
  554.   if ((sbUseVer<1)||(sbUseVer>4))
  555.     return 0;
  556.  
  557.   if (ver<sbUseVer)
  558.     return 0;
  559.   if ((ver==4)&&(sbUseVer==3))
  560.     return 0;
  561.  
  562.   if (sbIRQ==-1)
  563.   {
  564.     if (sbUseVer!=4)
  565.     {
  566.       unsigned char irqs[]={7, 5, 2, 3, 10};
  567.       for (i=0; i<sizeof(irqs); i++)
  568.         if (testirq(irqs[i]))
  569.           break;
  570.       if (i==sizeof(irqs))
  571.         return 0;
  572.       sbIRQ=irqs[i];
  573.     }
  574.     else
  575.     {
  576.       unsigned char a=readMixer(0x80);
  577.       if (!(a&0x0F))
  578.         return 0;
  579.       sbIRQ=(a&2)?5:(a&4)?7:(a&1)?2:10;
  580.     }
  581.   }
  582. //  else
  583. //    if (!testirq(sbIRQ))
  584. //      return 0;
  585.  
  586.   if (sbDMA==-1)
  587.   {
  588.     if (sbUseVer!=4)
  589.     {
  590.       unsigned char dmas[]={1, 0, 3};
  591.       for (i=0; i<sizeof(dmas); i++)
  592.         if (testdma(sbIRQ, dmas[i]))
  593.           break;
  594.       if (i==sizeof(dmas))
  595.         return 0;
  596.       sbDMA=dmas[i];
  597.     }
  598.     else
  599.     {
  600.       unsigned char b=readMixer(0x81);
  601.       if (!(b&0x0B))
  602.         return 0;
  603.       sbDMA=(b&2)?1:(b&1)?0:3;
  604.     }
  605.   }
  606. //  else
  607. //    if (!testdma(sbIRQ, sbDMA))
  608. //      return 0;
  609.  
  610.   if (sbUseVer==4)
  611.   {
  612.     if (sbDMA16==-1)
  613.     {
  614.       unsigned char b=readMixer(0x81);
  615.       if (!(b&0x0B))
  616.         return 0;
  617.       sbDMA16=(b&0x20)?5:(b&0x40)?6:(b&0x80)?7:sbDMA;
  618.     }
  619. //    else
  620. //      if (!testdma16(sbIRQ, sbDMA16))
  621. //        return 0;
  622.   }
  623.   else
  624.     sbDMA16=-1;
  625.  
  626.   card.dev=&smpSoundBlaster;
  627.   card.port=sbPort;
  628.   card.port2=-1;
  629.   card.irq=sbIRQ;
  630.   card.irq2=-1;
  631.   card.dma=sbDMA;
  632.   card.dma2=sbDMA16;
  633.   card.subtype=sbUseVer;
  634.   card.mem=0;
  635.   card.chan=(card.subtype<3)?1:2;
  636.  
  637.   return 1;
  638. }
  639.  
  640. extern "C" sounddevice smpSoundBlaster={SS_SAMPLER, "SoundBlaster", sbDetect, sbInit, sbClose};
  641.  
  642. #include "devigen.h"
  643. #include "psetting.h"
  644.  
  645. static unsigned long sbGetOpt(const char *sec)
  646. {
  647.   unsigned long opt=0;
  648.   if (cfGetProfileBool(sec, "sbrevstereo", 0, 0))
  649.     opt|=SS_SB_REVSTEREO;
  650.   return opt;
  651. }
  652.  
  653. extern "C" devaddstruct smpSBAdd = {sbGetOpt, 0, 0, 0};
  654.